import argparse

import pandas
from jiralib import JiraOp, Item
from jiralib import ISSUE_TYPE_CA_ITEM, ISSUE_TYPE_EPIC_ITEM


def parse_argment():
    parser = argparse.ArgumentParser()
    parser.add_argument("-f", "--file", help="File name of excel file")
    parser.add_argument("-s", "--sheetname", help="Worksheet of excel file")

    args_l = parser.parse_args()
    if not args_l.file or not args_l.sheetname:
        print(parser.print_help())
        exit(1)

    import os
    if not os.path.isfile(args_l.file):
        print('Excel file does not existing!')
        print(parser.print_help())
        exit(1)

    return args_l


__HEADER__ = '    '
__CREATE_FSY__ = 'Create FSY'
__CREATE_SI__ = 'Create SI'
__CREATE_EI__ = 'Create EI'
__CREATE_CA__ = 'Create CA'
__CREATE_EPIC__ = 'Create EPIC'
__UPDATE_ITEM__ = 'Update Plan'
__CREATE_EE__ = 'Create EE'
__COMMIT_CA__ = 'Commit CA'
__POSTPONE_CA__ = 'Postpone CA'


def pause_and_wait():
    input('Press Enter to continue')


class Task(object):
    def __init__(self, task_name: str, parameters: dict):
        self.item_key = ''
        self.feature_id = ''
        self.description = ''
        self.requirement_area_owner = ''
        self.requirement_area_owner_account = ''
        self.sub_id = ''
        self.title = ''
        self.summary = ''
        self.ei_id = ''
        self.requirement_area = ''
        self.contact_person = ''
        self.contact_person_account = ''
        self.assignee = ''
        self.assignee_account = ''
        self.start_fb = ''
        self.end_fb = ''
        self.original_estimate = 0
        self.status = ''
        self.competence_area = ''
        self.activity_type = ''
        self.sub_activity_type = ''
        self.commit_status = ''
        self.delay_reason = ''
        self.delay_explanation = ''
        self.create_epic = ''
        self.label = ''
        self.task_name = task_name
        self.__str_parameters__ = {
            __CREATE_FSY__: self.__str_create_fsy_parameters__,
            __CREATE_SI__: self.__str_create_si_parameters__,
            __CREATE_EI__: self.__str_create_ei_parameters__,
            __CREATE_CA__: self.__str_create_ca_parameters__,
            __CREATE_EPIC__: self.__str_create_epic_parameters__,
            __UPDATE_ITEM__: self.__str_update_item_parameters__,
            __CREATE_EE__: self.__str_create_ee_parameters__,
            __COMMIT_CA__: self.__str_commit_ca_parameters__,
            __POSTPONE_CA__: self.__str_postpone_ca_parameters__
        }
        __initiator__ = {
            __CREATE_FSY__: self.__create_fsy_parameters__,
            __CREATE_SI__: self.__create_si_parameters__,
            __CREATE_EI__: self.__create_ei_parameters__,
            __CREATE_CA__: self.__create_ca_parameters__,
            __CREATE_EPIC__: self.__create_epic_parameters__,
            __UPDATE_ITEM__: self.__update_item_parameters__,
            __CREATE_EE__: self.__create_ee_parameters__,
            __COMMIT_CA__: self.__commit_ca_parameters__,
            __POSTPONE_CA__: self.__postpone_ca_parameters__
        }
        __initiator__[task_name](parameters)

    def __str__(self):
        return str(self.__str_parameters__[self.task_name]())

    def __create_fsy_parameters__(self, parameters: dict):
        self.feature_id = parameters['Internal Feature ID']
        self.title = parameters['Title']

        self.summary = '%s %s' % (self.feature_id, self.title)
        self.description = parameters['Description']
        self.requirement_area = parameters['Requirement Area']
        self.requirement_area_owner = parameters['Requirement Area Owner']
        self.requirement_area_owner_account = parameters['RAO Account']
        self.label = parameters['Label']

    def __str_create_fsy_parameters__(self):
        return {
            'Internal Feature ID': self.feature_id,
            'Title': self.title,
            'Summary': self.summary,
            'Description': self.description,
            'Requirement Area': self.requirement_area,
            'Requirement Area Owner': self.requirement_area_owner,
            'RAO Account': self.requirement_area_owner_account,
            'Label': self.label
        }

    def __create_si_parameters__(self, parameters: dict):
        self.item_key = parameters['Feature Item']
        self.sub_id = parameters['Sub ID']
        self.title = parameters['Title']

    def __str_create_si_parameters__(self):
        return {
            'Feature Item': self.item_key,
            'Sub ID': self.sub_id,
            'Title': self.title
        }

    def __create_ei_parameters__(self, parameters: dict):
        self.item_key = parameters['System Item']
        self.ei_id = parameters['EI-ID']
        self.title = parameters['Title']

    def __str_create_ei_parameters__(self):
        return {
            'System Item': self.item_key,
            'EI-ID': self.ei_id,
            'Title': self.title
        }

    def __create_ca_parameters__(self, parameters: dict):
        self.item_key = parameters['Entity Item']
        self.summary = parameters['Summary']
        self.contact_person = parameters['Contact Person']
        self.assignee = parameters['Assignee']
        self.competence_area = parameters['Competence Area']
        self.activity_type = parameters['Activity Type']
        self.sub_activity_type = parameters['Sub-activity Type']
        self.create_epic = parameters['Create EPIC']
        self.assignee_account = parameters['Assignee-Account']
        self.contact_person_account = parameters['Contact Person-Account']

    def __str_create_ca_parameters__(self):
        return {
            'Entity Item': self.item_key,
            'Summary': self.summary,
            'Contact Person': self.contact_person,
            'Assignee': self.assignee,
            'Competence Area': self.competence_area,
            'Activity Type': self.activity_type,
            'Sub-activity Type': self.sub_activity_type,
            'Create EPIC': self.create_epic,
            'Assignee-Account': self.assignee_account,
            'Contact Person-Account': self.contact_person_account
        }

    def __create_epic_parameters__(self, parameters: dict):
        self.item_key = parameters['CA Item']
        self.requirement_area = parameters['Requirement Area']
        self.summary = parameters['Summary']
        self.contact_person = parameters['Contact Person']
        self.assignee = parameters['Assignee']
        self.start_fb = str(int(float(parameters['Start FB']))) if parameters['Start FB'] else ''
        self.end_fb = str(int(float(parameters['End FB']))) if parameters['End FB'] else ''
        self.original_estimate = int(float(parameters['Effort'])) if parameters['Effort'] else 0
        self.status = parameters['Status']
        self.contact_person_account = parameters['Contact Person-Account']
        self.assignee_account = parameters['Assignee-Account']

    def __str_create_epic_parameters__(self):
        return {
            'CA Item': self.item_key,
            'Requirement Area': self.requirement_area,
            'Summary': self.summary,
            'Contact Person': self.contact_person,
            'Assignee': self.assignee,
            'Start FB': self.start_fb,
            'End FB': self.end_fb,
            'Effort': self.original_estimate,
            'Status': self.status,
            'Contact Person-Account': self.contact_person_account,
            'Assignee-Account': self.assignee_account
        }

    def __update_item_parameters__(self, parameters: dict):
        self.item_key = parameters['CA/EPIC Item']
        self.start_fb = parameters['Start FB']
        self.end_fb = parameters['End FB']
        self.original_estimate = parameters['Effort']
        self.status = parameters['Status']
        self.contact_person = parameters['Contact Person']
        self.contact_person_account = parameters['Contact Person-Account']

    def __str_update_item_parameters__(self):
        return {
            'CA/EPIC Item': self.item_key,
            'Start FB': self.start_fb,
            'End FB': self.end_fb,
            'Effort': self.original_estimate,
            'Status': self.status,
            'Contact Person': self.contact_person,
            'Contact Person-Account': self.contact_person_account
        }

    def __create_ee_parameters__(self, parameters: dict):
        pass

    def __str_create_ee_parameters__(self):
        pass

    def __commit_ca_parameters__(self, parameters: dict):
        pass

    def __str_commit_ca_parameters__(self):
        pass

    def __postpone_ca_parameters__(self, parameters: dict):
        self.item_key = parameters['CA Item']
        self.end_fb = parameters['End FB']
        self.delay_reason = parameters['Delay Reason']
        self.delay_explanation = parameters['Delay Explanation']

    def __str_postpone_ca_parameters__(self):
        return {
            'CA Item': self.item_key,
            'End FB': self.end_fb,
            'Delay Reason': self.delay_reason,
            'Delay Explanation': self.delay_explanation
        }


class JiraTasks(object):
    def __init__(self, file_name, sheet_name):
        self.file_name = file_name
        self.task_name = sheet_name
        self.task_list = []
        import warnings
        warnings.simplefilter('ignore', category=UserWarning)
        excel = pandas.read_excel(self.file_name, sheet_name=sheet_name, engine='openpyxl')
        for value in excel.values:
            row_value = {}
            if str(value[0]) != 'nan':
                for i, key in enumerate(excel.columns.values):
                    if 'Unnamed' not in key:
                        row_value[key] = str(value[i]).lstrip().rstrip() if str(value[i]) != 'nan' else ''
                self.task_list.append(Task(sheet_name, row_value))


class Handler:
    def __init__(self, file_name, sheet_name):
        self.jira = JiraOp()
        self.tasks = JiraTasks(file_name, sheet_name)
        self.task_handlers = {
            __CREATE_FSY__: self.__handler_create_fsy_feature__,
            __CREATE_SI__: self.__handler_create_system_item__,
            __CREATE_EI__: self.__handler_create_entity_item__,
            __CREATE_CA__: self.__handler_create_ca_item__,
            __CREATE_EPIC__: self.__handler_create_epic_item__,
            __UPDATE_ITEM__: self.__handler_update_item__,
            __CREATE_EE__: self.__handler_create_ee_ticket_eta__,
            __COMMIT_CA__: self.__handler_update_commit_status__,
            __POSTPONE_CA__: self.__handler_postpone_ca_item__
        }

    def execute(self):
        if self.tasks.task_name not in self.task_handlers.keys():
            print('Excel sheet name is changed. Supported names:\n', self.task_handlers.keys())
        else:
            for task in self.tasks.task_list:
                self.task_handlers[self.tasks.task_name](task)

    def __get_jira_item_for_task(self, task: Task) -> Item:
        item = self.jira.item(task.item_key)
        item.print_basic_info()
        return item

    def __handler_create_fsy_feature__(self, task: Task):
        if_item = self.jira.create_internal_feature(feature_id=task.feature_id, summary=task.summary,
                                                    description=task.description,
                                                    rao_account=task.requirement_area_owner_account,
                                                    label=task.label)

        # if_item = self.jira.item('FFB-36105')
        if_item.print_basic_info()
        # Update Requirement Area
        if_item.update_requirement_area(task.requirement_area)
        print(if_item.prin_indent(), "    Update Requirement Area  :  ", if_item.get_requirement_area())

        # Update Assignee
        if_item.update_assignee(task.requirement_area_owner_account)
        print(if_item.prin_indent(), "    Update Assignee  :  ", if_item.get_assignee().display_name)

    def __handler_create_system_item__(self, task: Task):
        feature_item = self.__get_jira_item_for_task(task)

        system_item = self.jira.create_system_item(feature_item)
        if system_item:
            # system_item = self.jira.item('FPB-722344')
            system_item.print_basic_info()

            # Update Summary
            feature_id = feature_item.get_feature_id()
            summary = '%s-%s %s' % (feature_id, task.sub_id, task.title)
            system_item.update_summary(summary)
            print(feature_item.prin_indent(), "    Update Summary  :  ", system_item.get_summary())

            # Update Item ID
            item_id = '%s-%s' % (feature_id, task.sub_id)
            system_item.update_item_id(item_id)
            print(system_item.prin_indent(), "    Update Item ID  :  ", system_item.get_item_id())
        else:
            print('ERROR: create system item failed', feature_item)

    def __handler_create_entity_item__(self, task: Task):
        system_item = self.__get_jira_item_for_task(task)

        entity_item = self.jira.create_entity_item(system_item)
        if entity_item:
            entity_item.print_basic_info()

            # Update Summary
            system_item_id = system_item.get_item_id()
            summary = '%s-%s %s' % (system_item_id, task.ei_id, task.title)
            entity_item.update_summary(summary)
            print(entity_item.prin_indent(), "    Update Summary  :  ", summary)

            # Update Item ID
            item_id = '%s-%s' % (system_item_id, task.ei_id)
            entity_item.update_item_id(item_id)
            print(entity_item.prin_indent(), "    Update Item ID  :  ", item_id)

    def __handler_create_ca_item__(self, task: Task):
        ei_item = self.__get_jira_item_for_task(task)

        ca_item = self.jira.get_new_ca_item(ei_item, task.competence_area)
        if ca_item:
            ca_item.print_basic_info()

            # Update Summary
            if not task.competence_area in task.summary:
                ca_item.update_summary("%s-%s" % (task.summary, task.competence_area))
                print(ca_item.prin_indent(), "    Update Summary  :  ", ca_item.get_summary())

            # Update assignee
            ca_item.update_assignee(task.assignee_account)
            print(ca_item.prin_indent(), "    Update Assignee  :  ", ca_item.get_assignee().display_name)

            # Update contact person
            if task.contact_person_account:
                ca_item.update_contact_person(task.contact_person_account)
                print(ca_item.prin_indent(), "    Update Contact Person  :  ",
                      ca_item.get_contact_person_display_name())

            # Update Activity Type
            ca_item.update_activity_type(task.activity_type)
            print(ca_item.prin_indent(), "    Update Activity Type  :  ", ca_item.get_activity_type())

            # Update Sub-activity Type
            ca_item.update_sub_activity_type(task.sub_activity_type)
            print(ca_item.prin_indent(), "    Update Sub-activity Type  :  ", ca_item.get_sub_activity_type())

            item_id = ca_item.get_item_id()
            if 'FSY' in item_id:
                # For FSY item update FB commitment and release commitment
                ca_item.update_fb_commit_status(False)
                ca_item.update_release_commit_status(False)

            if task.create_epic == 'Yes':
                new_task = Task(task_name=__CREATE_EPIC__,
                                parameters={
                                    'CA Item': ca_item.key,
                                    'Requirement Area': task.competence_area,
                                    'Contact Person': task.contact_person,
                                    'Assignee': task.assignee,
                                    'Start FB': '',
                                    'End FB': '',
                                    'Effort': '',
                                    'Status': '',
                                    'Contact Person-Account': task.contact_person_account,
                                    'Assignee-Account': task.assignee_account})
                self.__handler_create_epic_item__(new_task)

    def __handler_create_epic_item__(self, task: Task):
        ca_item = self.__get_jira_item_for_task(task)

        epic_item = self.jira.get_new_epic_for_ca(ca_item)

        # Update summary
        if task.summary != '':
            if not task.requirement_area in task.summary:
                summary = "%s-%s" % (task.summary, task.requirement_area)
                epic_item.update_summary(summary)
                epic_item.issue.update({"customfield_12791": summary})
            else:
                epic_item.update_summary(task.summary)
                epic_item.issue.update({"customfield_12791": task.summary})
        else:
            summary = epic_item.get_summary()
            if not task.requirement_area in summary:
                epic_item.update_summary("%s-%s" % (epic_item.get_summary(), task.requirement_area))
        epic_item.print_basic_info()

        # Update Assignee
        epic_item.update_assignee(task.assignee_account)
        print(epic_item.prin_indent(), "    Update Assignee  :  ", epic_item.get_assignee().display_name)

        # Update contact person
        if task.contact_person_account:
            epic_item.update_contact_person(task.contact_person_account)
            print(epic_item.prin_indent(), "    Update Contact Person : ", epic_item.get_contact_person_display_name())

        # Update Start FB
        if task.start_fb:
            epic_item.update_start_fb(task.start_fb)
            print(epic_item.prin_indent(), "    Update Start FB : ", epic_item.get_start_fb())

        # Update End FB
        if task.end_fb:
            epic_item.update_end_fb(task.end_fb)
            print(epic_item.prin_indent(), "    Update End FB : ", epic_item.get_end_fb())

        # Update Original Estimation
        if task.original_estimate:
            epic_item.update_original_estimate(task.original_estimate)
            print(epic_item.prin_indent(), "    Update Original Estimate : ", epic_item.get_original_estimate())

        # Change Item Status
        if task.status:
            epic_item.change_status(task.status)
            print(epic_item.prin_indent(), "    Update Status : ", task.status)

    def __handler_update_item__(self, task: Task):
        item = self.__get_jira_item_for_task(task)
        item.assert_item_type([ISSUE_TYPE_CA_ITEM, ISSUE_TYPE_EPIC_ITEM])

        if task.contact_person_account:
            item.update_contact_person(task.contact_person_account)
            print(item.prin_indent(), '    Update contact : %s' % item.get_contact_person_display_name())

        if task.original_estimate:
            item.update_original_estimate(task.original_estimate)
            print(item.prin_indent(), '    Update Original Estimate : %s' % item.get_original_estimate())

        if task.start_fb:
            item.update_start_fb(task.start_fb)
            print(item.prin_indent(), '    Update Start FB : %s' % item.get_start_fb())

        if task.end_fb:
            item.update_end_fb(task.end_fb)
            print(item.prin_indent(), '    Update End FB : %s' % item.get_end_fb())

        if task.status:
            item.change_status(task.status)
            print(item.prin_indent(), '    Update Status : %s' % task.status)

    def __handler_create_ee_ticket_eta__(self, task: Task):
        print(task)

    def __handler_update_commit_status__(self, task: Task):
        print(task)

    def __handler_postpone_ca_item__(self, task: Task):
        print(task)
        ca_item = self.__get_jira_item_for_task(task)

        ca_item.update_delay_reason(task.delay_reason)
        print(ca_item.prin_indent(), '    Update delay reason : %s' % ca_item.get_delay_reason())

        ca_item.update_delay_explain(task.delay_explanation)
        print(ca_item.prin_indent(), '    Update delay explain : %s' % ca_item.get_delay_explain())

        ca_item.update_end_fb(task.end_fb)
        print(ca_item.prin_indent(), '    Update End FB : %s' % ca_item.get_end_fb())


if __name__ == '__main__':
    args = parse_argment()
    # task = JiraTasks(args.file, args.sheetname)
    try:
        handler = Handler(args.file, args.sheetname)
        handler.execute()
    except Exception as err:
        print(err)

    pause_and_wait()
